﻿using Manon.Repository.Collections;
using Manon.Repository.Repository;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Query;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;

namespace Manon.Repository
{
    public interface IRepository<TEntity> : IRepository<TEntity, int> where TEntity : class, IAggregateRoot<int>
    {

    }


    /// <summary>
    /// 通用仓储接口
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public interface IRepository<TEntity, TId> where TEntity : class, IAggregateRoot<TId>
    {
        #region  查询



        #region 条件查询
        /// <summary>
        /// 根据条件查询，返回IQueryable<TEntity>
        /// </summary>
        /// <param name="where">查询添加，可以为空</param>
        /// <returns></returns>
        IQueryable<TEntity> GetQuery();

        /// <summary>
        /// 根据条件查询，返回IQueryable<TEntity>
        /// </summary>
        /// <param name="where">查询添加，可以为空</param>
        /// <returns></returns>
        IQueryable<TEntity> GetQuery(Expression<Func<TEntity, bool>> where);

        /// <summary>
        /// 根据条件查询，返回IQueryable<TEntity>
        /// </summary>
        /// <param name="where">查询添加，可以为空</param>
        /// <returns></returns>
        IQueryable<TSelector> GetQuery<TSelector>(Expression<Func<TEntity, TSelector>> selector);

        /// <summary>
        /// 根据条件查询，返回IQueryable<TEntity>
        /// </summary>
        /// <param name="where">查询添加，可以为空</param>
        /// <returns></returns>
        IQueryable<TSelector> GetQuery<TSelector>(Expression<Func<TEntity, bool>> where, Expression<Func<TEntity, TSelector>> selector);


        /// <summary>
        /// 根据条件查询，返回IQueryable,不可追踪<TEntity>
        /// </summary>
        /// <param name="where">查询添加，可以为空</param>
        /// <returns></returns>
        IQueryable<TEntity> GetQueryAsNoFilter();


        /// <summary>
        /// 根据条件查询，返回IQueryable,不可追踪<TEntity>
        /// </summary>
        /// <param name="where">查询添加，可以为空</param>
        /// <returns></returns>
        IQueryable<TEntity> GetQueryAsNoFilter(Expression<Func<TEntity, bool>> where);


        /// <summary>
        /// 异步条件查询，返回实体集合. 状态不可追踪
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        Task<IEnumerable<TEntity>> GetListAsync(CancellationToken cancellationToken = default);


        /// <summary>
        /// 异步条件查询，返回实体集合. 状态不可追踪
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        Task<IEnumerable<TSelector>> GetListIncludeAsync<TSelector>(Expression<Func<TEntity, bool>> where, Expression<Func<TEntity, TSelector>> selector, Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> include, CancellationToken cancellationToken = default);

        /// <summary>
        /// 异步条件查询，返回实体集合. 状态不可追踪
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        Task<IEnumerable<TEntity>> GetListIncludeOnlyAsync<TProperty>(Expression<Func<TEntity, bool>> where, Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, TProperty>> include, CancellationToken cancellationToken = default);

        /// <summary>
        /// 异步条件查询，返回实体集合. 状态不可追踪
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        Task<IEnumerable<TSelector>> GetListAsync<TSelector>(Expression<Func<TEntity, TSelector>> selector, CancellationToken cancellationToken = default);


        /// <summary>
        /// 异步条件查询，返回实体集合. 状态不可追踪
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        Task<IEnumerable<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> where, CancellationToken cancellationToken = default);

        /// <summary>
        /// 异步条件查询，返回实体集合. 状态不可追踪
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        Task<IEnumerable<TSelector>> GetListAsync<TSelector>(Expression<Func<TEntity, bool>> where, Expression<Func<TEntity, TSelector>> selector, CancellationToken cancellationToken = default);


        /// <summary>
        /// 异步条件查询，返回实体集合. 状态不可追踪
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        Task<IEnumerable<TEntity>> GetListAsNoFilterAsync(CancellationToken cancellationToken = default);

        /// <summary>
        /// 异步条件查询，返回实体集合. 状态不可追踪
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        Task<IEnumerable<TEntity>> GetListAsNoFilterAsync(Expression<Func<TEntity, bool>> where, CancellationToken cancellationToken = default);

        /// <summary>
        /// 异步条件查询，返回自定义实体集合. 状态不可追踪
        /// </summary>
        /// <typeparam name="TTarget"></typeparam>
        /// <param name="where"></param>
        /// <returns></returns>
        Task<IEnumerable<TTarget>> GetListAsync<TTarget>();

        /// <summary>
        /// 异步条件查询，返回自定义实体集合. 状态不可追踪
        /// </summary>
        /// <typeparam name="TTarget"></typeparam>
        /// <param name="where"></param>
        /// <returns></returns>
        Task<IEnumerable<TTarget>> GetListAsync<TTarget>(Expression<Func<TEntity, bool>> where);

        /// <summary>
        /// 异步条件查询，返回自定义实体集合. 状态不可追踪
        /// </summary>
        /// <typeparam name="TTarget"></typeparam>
        /// <param name="where"></param>
        /// <returns></returns>
        Task<IEnumerable<TTarget>> GetListAsNoFilterAsync<TTarget>(Expression<Func<TEntity, bool>> where);
        #endregion

        #region 查询单条记录 

        /// <summary>
        /// 异步查询单条记录 ,状态不可追踪
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TEntity?> GetFirstOrDefaultAsync(CancellationToken cancellationToken = default(CancellationToken));
        /// <summary>
        /// 异步查询单条记录 ,状态不可追踪
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TSelector?> GetFirstOrDefaultAsync<TSelector>(Expression<Func<TEntity, TSelector>> selector, CancellationToken cancellationToken = default(CancellationToken));

        /// <summary>
        /// 异步查询单条记录 ,状态不可追踪
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TEntity?> GetFirstOrDefaultAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default(CancellationToken));


        /// <summary>
        /// 异步查询单条记录 ,状态不可追踪
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TSelector?> GetFirstOrDefaultAsync<TSelector>(Expression<Func<TEntity, bool>> predicate, Expression<Func<TEntity, TSelector>> selector, CancellationToken cancellationToken = default(CancellationToken));

        /// <summary>
        ///  异步查询单条记录 ,状态不可追踪
        /// </summary>
        /// <typeparam name="TTarget"></typeparam>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TTarget?> GetFirstOrDefaultAsync<TTarget>(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default);

        /// <summary>
        /// 异步查询单条记录 ,状态不可追踪
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TEntity?> GetFirstOrDefaultAsNoFilterAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default);

        /// <summary>
        ///  异步查询单条记录 ,状态不可追踪
        /// </summary>
        /// <typeparam name="TTarget"></typeparam>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TTarget?> GetFirstOrDefaultAsNoFilterAsync<TTarget>(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default);

        #endregion

        #endregion


        #region  count、exist

        /// <summary>
        /// 异步查询记录数
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<int> CountAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default);



        /// <summary>
        /// 异步查询是否存在
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> ExistsAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default);



        /// <summary>
        /// 异步查询记录数，忽略全局过滤
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<int> CountAsNoFilterAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default);

        /// <summary>
        /// 异步查询是否存在，忽略全局过滤
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> ExistsAsNoFilterAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default);
        #endregion



        #region 排序

        /// <summary>
        /// 排序 正序
        /// </summary>
        /// <param name="orderBy"></param>
        /// <returns></returns> 
        IOrderedQueryable<TEntity> OrderBy(Expression<Func<TEntity, TId>> keySelector);

        /// <summary>
        /// 排序 倒序
        /// </summary>
        /// <param name="orderBy"></param>
        /// <returns></returns>
        IOrderedQueryable<TEntity> OrderByDescending(Expression<Func<TEntity, TId>> keySelector);


        #endregion

        #region GetPagedList



        /// <summary>
        /// 异步获取分页
        /// </summary>
        /// <param name="where">条件</param>
        /// <param name="Input">分页参数</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<PagedList<TEntity>> GetPagedListAsync(Expression<Func<TEntity, bool>> where, BasePageInput Input, CancellationToken cancellationToken = default);

        /// <summary>
        /// 异步获取分页
        /// </summary>
        /// <param name="where">条件</param>
        /// <param name="Input">分页参数</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<PagedList<TSelector>> GetPagedListAsync<TSelector>(Expression<Func<TEntity, bool>> where, BasePageInput Input, Expression<Func<TEntity, TSelector>> selector, CancellationToken cancellationToken = default);



        /// <summary>
        /// 异步获取分页列表，并返回指定的TResult类型
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="where">条件</param>
        /// <param name="Input">分页参数</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<PagedList<TResult>> GetPagedListAsync<TResult>(Expression<Func<TEntity, bool>> where, BasePageInput Input, CancellationToken cancellationToken = default);



        /// <summary>
        /// 异步获取分页列表，并返回指定的TResult类型
        /// </summary>
        /// <typeparam name="TResult"></typeparam> 
        /// <param name="Input">分页参数</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<PagedList<TResult>> GetPagedListAsync<TResult>(BasePageInput Input, CancellationToken cancellationToken = default);

        /// <summary>
        /// 异步获取分页
        /// </summary>
        /// <param name="where">条件</param>
        /// <param name="Input">分页参数</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<PagedList<TEntity>> GetPagedListAsNoFilterAsync(Expression<Func<TEntity, bool>> where, BasePageInput Input, CancellationToken cancellationToken = default);

        /// <summary>
        /// 异步获取分页列表，并返回指定的TResult类型
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="where">条件</param>
        /// <param name="Input">分页参数</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<PagedList<TResult>> GetPagedListAsNoFilterAsync<TResult>(Expression<Func<TEntity, bool>> where, BasePageInput Input, CancellationToken cancellationToken = default);

        /// <summary>
        /// 异步获取分页列表，并返回指定的TResult类型
        /// </summary>
        /// <typeparam name="TResult"></typeparam> 
        /// <param name="Input">分页参数</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<PagedList<TResult>> GetPagedListAsNoFilterAsync<TResult>(BasePageInput Input, CancellationToken cancellationToken = default);

        #endregion






        #region Insert

        ValueTask<EntityEntry<TEntity>> InsertAsync(TEntity entity, CancellationToken cancellationToken = default(CancellationToken));

        ValueTask<EntityEntry<TEntity>> InsertAsync(TEntity entity, object userId, CancellationToken cancellationToken = default(CancellationToken));



        Task InsertAsync(IEnumerable<TEntity> entities, CancellationToken cancellationToken = default(CancellationToken));
        Task InsertAsync(IEnumerable<TEntity> entities, object userId, CancellationToken cancellationToken = default(CancellationToken));
        #endregion

        #region Update

        Task UpdateAsync<TSelector>(TEntity entity, Expression<Func<TEntity, TSelector>> selector);

        Task UpdateAsync<TSelector>(IEnumerable<TEntity> entities, Expression<Func<TEntity, TSelector>> selector);


        Task UpdateAsync(TEntity entity);



        Task UpdateAsync(IEnumerable<TEntity> entities);

        Task UpdateAsync(TEntity entity, object userId);


        Task UpdateAsync(IEnumerable<TEntity> entities, object userId);
        #endregion

        #region Delete

        Task DeleteAsync(TEntity entity);



        Task DeleteAsync(object id);

        Task DeleteAsync(IEnumerable<TEntity> entities);

        Task DeleteLogicAsync(IEnumerable<TEntity> entities, object userId = null);
        Task DeleteLogicAsync(TEntity entity, object userId = null);

        Task DeleteLogicAsync(object id, object userId = null);


        #endregion




        #region sql相关
        /// <summary>
        /// 执行原生sql语句 
        /// </summary>
        /// <param name="sql">sql语句</param>
        /// <param name="parameters">参数</param>
        /// <returns></returns>
        Task<int> ExecuteSqlCommandAsync(string sql, params object[] parameters);


        #endregion


        Task<string> GetNo<Tentity>(int length);
    }
}
